/**
 * @file Forker.h
 * @author huangxiaozhu (huangxiaozhu@hxz.com)
 * @brief  货叉驱动控制对象，这是一个复合的硬件模拟对象，包含对货叉升降电机的控制和到位的io传感器的设置。
 * @version 0.1
 * @date 2023-12-11
 * 
 * @copyright Copyright (c) 2023
 * 
 */
#pragma once

#include "DriverModule/BaseDriver.h"
#include "tools/ThreadObj/ThreadObj.h"
#include <atomic>

// 模拟参数配置
const int FORK_WORKING_TIME_INTERVAL = 10;          // 模拟货叉升降的时间间隔(10ms)
const int FORK_WORKING_SPEED = 200;                 // 模拟货叉升降的速度 200mm/s

const int FORKER_MAX_HEIGHT = 3000;                 // 货叉的最大高度
const int FORKER_MIN_HEIGHT = 0;                    // 货叉的最小高度
const int FORKER_ERROR_RANGE = 5;                   // 允许货叉到位的误差范围。


enum ForkerDir
{
    FD_NONE = 0,     // 无操作，目标位置与当前位置一样，不需要升降货叉。
    FD_UP = 1,       // 升降货叉
    FD_DOWN = 2      // 升降货叉
};


class Forker;
using ForkerPtr = std::shared_ptr<Forker>;
/**
 * @brief Forker模拟叉车上的升叉机构，包含控制升降的模拟控制和货叉到位的模拟
 * 
 */
class Forker : public BaseDriver, public ThreadObj
{
public:
    Forker(const std::string& name = "");
    virtual ~Forker();

    virtual bool Init() override;

    virtual int DoTask() override;                      // handle fork.  模拟货叉的升降工作

    void SetEnable(bool enable);
    bool IsEnable();

    void SetTargetHeight(ushort height);                // 设置货叉目标高度
    ushort GetCurrentHeight();
    ushort GetTargetHeight();

    bool GetUpIO();                                     // 获取货叉上到位的io
    bool GetDownIO();                                   // 获取货叉下到位的io

    // 货叉升降的模拟控制
    void SetSpeed(int speed);
    int GetSpeed();
    void SetTimeInterval(int timeInterval);

protected:
    std::atomic_ushort m_currentHeight{0};              // 当前高度
    std::atomic_ushort m_targetHeight{0};               // 启动升叉时候，如果没有目标高度，此目标高度需要再次同步为当前的高度。


private:
    // 以下参数主要是模拟货叉的升降控制，利用线程进行模拟
    bool m_enable = false;                              // 是否开启，启动也是代表着这个升叉动作正在执行
    int m_speed = FORK_WORKING_SPEED;                   // 升叉速度。假设5秒升高1米（1000毫米），那么速度就是200mm/s。  m_speed = m_timeInterval * m_timeIntervalSpeed;
    int m_timeInterval = FORK_WORKING_TIME_INTERVAL;    // 模拟货叉升降的时间间隔，时间间隔越小，处理升叉动作幅度越丝滑。
    int m_timeIntervalSpeed = 20;                       // 时间间隔内的升叉速度。 模拟情况下，实际使用上，每个时间检测的速度计算如下。

    ForkerDir m_dir = ForkerDir::FD_NONE;               // 本次任务是上升或是下降

    bool m_beStop = false;                              // 工作线程是否启动。
    ThreadCond m_cond;                                  // 用于等待时间，同时提供退出的条件变量
};
